<?php
/*
	Plugin Name: wp-sam
	Version: 0.1
	Description: SDrop Admin Menu or SAM is an alternative to the regular WordPress administration menu. Providing a dropdown interface below the heading line SAM provides a means of navigation between pages of the administration area using a lightweight jquery and hoverIntent powered menu.
*/
/*
	Copyright (C) 2010 - t31os

	This program is free software; you can redistribute it and/or
	modify it under the terms of the GNU General Public License
	as published by the Free Software Foundation; either version 2
	of the License, or (at your option) any later version.

	This program is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with this program; if not, write to the Free Software
	Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
*/
if( class_exists( 'wp_sam' ) ) {
	die('Another script is using the class name');
}
else {
	class wp_sam {
		var $content_ref = 'post_types';
		var $sam_parents;
		var $sam_children;
		function wp_sam() {
			if( version_compare( PHP_VERSION, "5.0.0","<" ) ) {
				$this->__construct();
			}
		}
		function __construct() {
			//add_action( 'adminmenu',           array( $this, 'sam_validate_original_menu' ) ); // See comment in sam_save_menu_data()
			add_action( 'admin_menu',          array( $this, 'sam_add_menu_items' ) );
			add_action( 'admin_menu',          array( $this, 'sam_save_menu_data' ) , 10000 );
			add_action( 'admin_print_scripts', array( $this, 'sam_load_scripts' ) );
			add_action( 'admin_print_styles',  array( $this, 'sam_load_stylesheet' ) );
			add_action( 'in_admin_header',     array( $this, 'sam_admin_menu' ) );
		}
		function sam_add_menu_items() {
			// Top level item for holding post type items
			add_menu_page( ' ', 'Writing', 'manage_options', $this->content_ref, false, false );
			
			// Add new comments sub items
			add_submenu_page( 'edit-comments.php', 'Pending',  'Pending',  'manage_options', 'edit-comments.php?comment_status=moderated' );
			add_submenu_page( 'edit-comments.php', 'Approved', 'Approved', 'manage_options', 'edit-comments.php?comment_status=approved' );
			add_submenu_page( 'edit-comments.php', 'In trash', 'In trash', 'manage_options', 'edit-comments.php?comment_status=trash' );
			add_submenu_page( 'edit-comments.php', 'Spam',     'Spam',     'manage_options', 'edit-comments.php?comment_status=spam' );
		}
		function sam_validate_original_menu() {
			echo '<li></li>'."\n";
		}
		function sam_load_scripts() {
			// Load sdrop jQuery
			wp_enqueue_script( 'sam_sdrop_js', plugins_url('wp-sam/jquery.sdrop.js'), array('jquery','hoverIntent'), '220810' );
			// Load jQuery code for this menu
			wp_enqueue_script( 'sam_setup_js', plugins_url('wp-sam/wp.sam.js'),       array('sam_sdrop_js'),         '220810', true );
		}
		function sam_load_stylesheet() {
			global $is_IE;
			// Give IE it's own stylesheet
			if( $is_IE )
				wp_enqueue_style( 'sam_menu_IE' , plugins_url('wp-sam/menu-ie.css'), false, '1.0' );
			else
				wp_enqueue_style( 'sam_menu_css', plugins_url('wp-sam/menu.css')   , false, '1.0' );
		}
		function sam_save_menu_data() {
			global $menu, $submenu;
			// Remove links
			unset( $menu[15] );
			$this->sam_parents = $menu;
			$this->sam_children = $submenu;
			// Unusable due to WP restriction, must render existing menu
			//$menu = $submenu = array();
		}
		function sam_admin_menu() {

			global $parent_file, $pagenow, $plugin_page, $submenu_file;
			
			$post_types_ref = $this->content_ref;
			
			// Hooks prior to doing any with the menu data
			$parent_items  = apply_filters( 'sam_parent_items', $this->sam_parents );
			$submenu_items = apply_filters( 'sam_child_items',  $this->sam_children );
			
			if( 'edit-comments.php' == $pagenow ) {
				$comment_types = array( 'moderated', 'approved', 'trash', 'spam' );
				if( isset( $_GET['comment_status'] ) ) {
					if( in_array( $_GET['comment_status'], $comment_types ) )
						$submenu_file = add_query_arg( 'comment_status', $_GET['comment_status'], $pagenow );
				}
			}
			
			// Work out the current admin page (the page being viewed)
			if( !empty( $plugin_page ) )
				// If $plugin_page is set, $pagenow + $plugin_page as the page query arg is the current URL
				$_the_url = $pagenow .'?page='. $plugin_page;
			
			elseif( !empty( $submenu_file ) )
				// If $submenu_file is set it holds the full URL
				$_the_url = $submenu_file;
			
			else
				// Else $pagenow is the current URL
				$_the_url = $pagenow;
				
			// Array to hold post type sub items (moving them all under one main menu, rather then several)
			$submenu_items[$post_types_ref] = array();
			
			// Rebuild menu arrays (personal change, easier to manage, read, etc)
			foreach( $parent_items as $parent_index => $item ) {
				
				// If the item is a seperator
				if( '' == $item[0] ) {
					unset( $parent_items[$parent_index] );
					continue;
				}

				// If the parent is edit.php it's a post type, merge into post type menu
				if( strlen( $item[2] ) >= 8 && ( 'edit.php' == substr( $item[2],0,8 ) ) ) {
					if( isset( $submenu_items[$item[2]] ) ) {
						// Move post type items into another menu
						$submenu_items[$post_types_ref] = array_merge( $submenu_items[$post_types_ref], $submenu_items[$item[2]] );
						// Drop originals
						unset( $submenu_items[$item[2]] );
						unset( $parent_items[$parent_index] );
						continue;
					}
				}
				// Hard to explain the logic here, but the $tree_now approach works pretty well
				$tree_now = false;
				// Post type links exist as submenu items, check $pagenow
				if( $post_types_ref == $item[2] ) {	
					if( 'edit.php' == $pagenow || 'edit-tags.php' == $pagenow || 'post-new.php' == $pagenow || 'post.php' == $pagenow )
						$tree_now = true;
				} 
				// Handle other cases
				else {	
					if( !empty( $parent_file ) ) {
						if( $parent_file == $item[2] ) {
							$tree_now = true;
						}
					}
					else {
						if( empty( $submenu_file ) && empty( $plugin_page ) ) {
							if( $pagenow == $item[2] ) {
								$tree_now = true;
							}
						}
					}
				}
				// Create array for children
				$children = array();
				
				// Check if this item has children
				if( isset( $submenu_items[$item[2]] ) ) {
					
					// Loop over children
					foreach( $submenu_items[$item[2]] as $child_index => $child ) {
						
						if( !current_user_can( $child[1] ) ) {
							unset( $submenu_items[$child_index] );
							continue;
						}
						/*
							Preserve offsite URLs, not supported in add_submenu_page, 
							but can be present if you add them to the menu array with a filter
						*/
						$first_chars = substr( $child[2], 0, 7 );
						if( 'http://' == $first_chars ) {
							// If an offsite URL, set file found, skips the file exists and URL pre/ap-pending
							$found_file = true;
						}
						else {
							// Check if the file exists as an admin file
							$file = ( false !== ( $pos = strpos( $child[2], '?' ) ) ) ? substr( $child[2], 0, $pos ) : $child[2];
							$found_file = ( file_exists( ABSPATH . '/wp-admin/' . $file ) ) ? true : false ;
						}
						/*
							No file found
						*/
						if( !$found_file ) {
							/* 
								If no file found, check if the parent exists as an admin or plugin file
								Prepend the value onto the end of the parent or admin.php as applicable
							*/
							if( file_exists( ABSPATH . '/wp-admin/' . $item[2] ) ) {
								$child[2] = $item[2] . '?page=' . $child[2];
							}
							elseif( file_exists( WP_PLUGIN_DIR . '/' . $item[2] ) ) {
								$item[10] = 'admin.php?page=' . $item[2];
								$child[2] = 'admin.php?page=' . $child[2];
							}
							/*
								Else no appending/prepending required, leave as is
							*/
						}
						/* 
							Add data to children array, preserving original index keys - but switching to named keys for the menu data
						*/
						$children[$child_index] = array(
							'name' => $child[0], 
							'cap' => $child[1], 
							'url' => $child[2]
						);
						// If the child item has a title, add it on
						if( isset( $child[3] ) && '' != $child[3] )
							$children[$child_index]['title'] = $child[3];
						
						// If this is the active tree, see if this child item's URL is the current one, mark if so
						if( $tree_now ) {
							if( $_the_url == $children[$child_index]['url'] )
								$children[$child_index]['active'] = 1;
						}
					}
				}
								
				if( !current_user_can( $item[1] ) && !count( $children ) ) {
					unset( $parent_items[$parent_index] );
					continue;
				}
				if( $item[2] == $post_types_ref ) {
					
				}
				// Switch to named keys for the parent items to, have also dealt with active/non-active status by this point
				$parent_items[$parent_index] = array( 
					'name' => $item[0],
					'cap' => $item[1],
					'url' => ( isset( $item[10] ) ? $item[10] : $item[2] ),
					'active' => ( $tree_now ? 1 : 0 ),
					'children' => $children
				);
				// If an icon is set (possibly by WordPress, using the generic icon)
				if( isset( $item[6] ) ) {
					if( 'div' != $item[6] ) {
						$parent_items[$parent_index]['icon'] = $item[6];
					}
				}
				if( isset( $item[4] ) && !isset( $parent_items[$parent_index]['icon'] ) ) {
					$parent_items[$parent_index]['classes'] = str_replace( array('menu-top-first','menu-top-last'), '', $item[4] );
				}
			}
			// Hook after menu data has been processed
			$parent_items = apply_filters( 'sam_menu_items', $parent_items );
			
			//print '<pre>';print_r( $a );print '</pre>';
			?>		
			<div class="clear"></div>
			<div id="sam-wrapper">
				<ul class="sam-main">
				<?php $this->sam_output( $parent_items ); ?>
				</ul>
				<div class="clear"></div>
			</div>
			<div class="clear"></div>
			<?php
		}
		function sam_output( $menu_items , $echo = true ) {
			
			if( !is_array( $menu_items ) || empty( $menu_items ) )
				return '';
			
			$return = '';
			$i = 0;
			
			foreach( $menu_items as $index => $menu_item ) {
				
				$name = $menu_item['name'];
				$active = $menu_item['active'];
				$classes = ( isset( $menu_item['classes'] ) ) ? $menu_item['classes'] : false;
				$icon = ( isset( $menu_item['icon'] ) ) ? $menu_item['icon'] : false;
				$url = $menu_item['url'];
				$children = $menu_item['children'];
				
				$i++;
				
				$onclick = '';
				$class = 'sam_item';
				$class .= ( $active ) ? ' sam_active' : '';
				$class .= ( $classes ) ? " $classes" : '';
	
				$return .= '<li class="'.$class.'">';
				
				if( 'post_types' == $url )
					$onclick = ' onclick="return false;"';
					
				$return .= "<div><a class=\"menu_link\"$onclick href=\"$url\"><span class=\"wp-icon\">&nbsp;</span>$name</a></div>";
				
					
				if( $children ) {
					
					$return .= '<ul class="hidden">';
					$ii = $when = 0;
					
					foreach( $children as $child_index => $child ) {
						
						if( !isset( $child['name'] ) || !isset( $child['url'] ) )
							continue;
						$ii++;
						
						$_the_parent = '';
						if( strlen( $child['url'] ) > 7 ) {
							$_the_parent = substr( $child['url'], 0, 8 );
						}
						if( 'edit.php' == $_the_parent ) {
							$when = $ii;
						}
						$childclass = 'sam_child';
						$childclass .= ( $ii > $when && 'post_types' == $url ) ? ' sub' : '';
						$childclass .= ( isset( $child['active'] ) && 1 == $child['active'] ) ? ' sam_active' : '';
						$childclass .= ( $ii == 1 ) ? ' first' : '';
						
						$return .= '<li class="'.$childclass.'"><a href="' . $child['url'] . '">' . $child['name'] .'</a></li>';
					}
					
					$return .= "</ul>";
				}
				
				$return .= '</li>';
				
			}
			$return .= '';
			
			if( $echo )
				echo $return;
			else
				return $return;
		}

	}
	$wp_sam = new wp_sam();
}